package pers.tz.题目.leetcode.链表;

import pers.tz.common.ListNode;
import pers.tz.common.ListUtils;

import java.util.Stack;

/**
 * @author irony
 * @date 2024-03-12
 */
public class LCR_027_回文链表 {
// 给定一个链表的 头节点 head ，请判断其是否为回文链表。
//如果一个链表是回文，那么链表节点序列从前往后看和从后往前看是相同的。
//
// 输入: head = [1,2,3,3,2,1]
//输出: true
//
// 输入: head = [1,2]
//输出: false
//
// 链表 L 的长度范围为 [1, 105]
//0 <= node.val <= 9
//
// 进阶：能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题？

    public static void main(String[] args) {
        ListNode l1 = new ListNode(1);
        ListNode l2 = new ListNode(2);
        ListNode l3 = new ListNode(3);
        ListNode l4 = new ListNode(2);
        ListNode l5 = new ListNode(1);
        l1.next = l2;
        l2.next = l3;
        l3.next = l4;
        l4.next = l5;
        ListUtils.printList(l1);

        System.out.println(isPalindrome(l1));
        System.out.println(isPalindrome2(l1));
    }

    // 可行解：栈
    public static boolean isPalindrome(ListNode head) {
        Stack<Integer> stack = new Stack<>();

        ListNode cur = head;
        while (cur != null) {
            stack.push(cur.val);
            cur = cur.next;
        }

        cur = head;
        while (cur != null) {
            if (stack.pop() != cur.val) {
                return false;
            }

            cur = cur.next;
        }

        return true;
    }

    // 最优解：快慢指针
    public static boolean isPalindrome2(ListNode head) {
        ListNode s = head;
        ListNode f = head;

        while (f != null && f.next != null) {
            f = f.next.next;
            s = s.next;
        }

        // 反转链表
        ListNode R = null;
        ListNode next = null;
        while (s != null) {
            next = s.next;
            s.next = R;

            R = s;
            s = next;
        }

        // 分别从最左、最右出发
        ListNode L = head;
        while (L != null && R != null) {
            if (L.val != R.val) {
                return false;
            }

            L = L.next;
            R = R.next;
        }

        return true;
    }
}
